Imports SharePointSchemaMigrator.MossWebs

Public Class FieldsMigrator
    Dim Columns As Xml.XmlNode
    Const newMethodNumber As String = "1"
    Const updateMethodNumber As String = "2"

    Public Sub New()
        ' This call is required by the Windows Form Designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.
        My.WebServices.Webs.Credentials = Net.CredentialCache.DefaultCredentials
        'My.WebServices.SiteData.Credentials = My.WebServices.Webs.Credentials
    End Sub

    Private Sub ButtonGet_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonGet.Click
        DataSetFields.Clear()
        Columns = Me.SourceWeb.GetColumns()

        'Dim sWebMetadata As New MossSiteData._sWebMetadata
        'My.WebServices.SiteData.GetWeb(sWebMetadata, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing)

        Dim row As DataSetFields.FieldsRow
        For Each node As Xml.XmlNode In Columns.ChildNodes
            row = DataSetFields.Fields.NewFieldsRow()
            Try
                row.Group = node.Attributes("Group").Value
            Catch ex As NullReferenceException
                'Ignore Null Group
            End Try
            row.ID = node.Attributes("ID").Value
            row.DisplayName = node.Attributes("DisplayName").Value
            row.Name = node.Attributes("Name").Value
            If Not row.IsGroupNull AndAlso row.Group <> "_Hidden" Then
                DataSetFields.Fields.AddFieldsRow(row)
            End If
        Next
        Me.ButtonCopy.Visible = True
        Me.Text = "Fields Migrator - " & DataSetFields.Fields.Count.ToString & " columns"
    End Sub

    Private Sub ButtonCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonCopy.Click
        Dim newFields As Xml.XmlNode = Columns.Clone
        Dim updateFields As Xml.XmlNode = Nothing
        Dim childNode As Xml.XmlNode
        Dim childName As String

        Do Until Not newFields.HasChildNodes
            newFields.RemoveChild(newFields.FirstChild)
        Loop

        updateFields = newFields.Clone

        Dim nsmgr As New Xml.XmlNamespaceManager(Columns.OwnerDocument.NameTable)
        nsmgr.AddNamespace("flds", Columns.NamespaceURI)

        For Each fieldrow As DataSetFields.FieldsRow In Me.DataSetFields.Fields
            childNode = Columns.SelectSingleNode("/flds:Field[@ID='" & fieldrow.ID & "']", nsmgr).Clone
            childName = childNode.Attributes("Name").Value

            If fieldrow.Update Then
                AppendChildToFields(fieldrow, updateFields, childNode, updateMethodNumber)
            End If
            If fieldrow.Copy Then
                If IsSameSiteCollection AndAlso childName = fieldrow.Name Then
                    'Copying same named column within a site collection.
                    MsgBox("Cannot copy a column within a site collection without changing the name.  Column """ & childName & """ will not be copied." & vbCrLf & "To move this column, copy the column with a new name, delete or rename the original, then update the new column's name.", MsgBoxStyle.OkOnly, "Unable to copy row.")
                Else
                    'Proceed with copy/update.
                    AppendChildToFields(fieldrow, newFields, childNode, newMethodNumber)
                End If
            End If
        Next

        'Execute Copy and Update
        Dim UpdateReturn As Xml.XmlNode
        Dim CopyReturn As Xml.XmlNode
        Dim ReturnMessage As String = String.Empty

        If newFields.HasChildNodes Then
            CopyReturn = Me.DestinationWeb.UpdateColumns(newFields, Nothing, Nothing)
            ReturnMessage &= "Copy:" & vbCrLf & CopyReturn.InnerXml & vbCrLf & vbCrLf
        End If
        If updateFields.HasChildNodes Then
            UpdateReturn = Me.SourceWeb.UpdateColumns(Nothing, updateFields, Nothing)
            ReturnMessage &= "Update:" & vbCrLf & UpdateReturn.InnerXml
        End If

        MsgBox(ReturnMessage, MsgBoxStyle.OkOnly, "Results")

        'Refresh the table
        Me.ButtonGet_Click(Nothing, Nothing)

    End Sub

    Private Sub AppendChildToFields(ByVal fieldRow As DataSetFields.FieldsRow, ByVal fields As Xml.XmlNode, ByVal childNode As Xml.XmlNode, ByVal methodNumber As String)
        childNode.Attributes("Name").Value = fieldRow.Name
        childNode.Attributes("DisplayName").Value = fieldRow.DisplayName
        childNode.Attributes("Group").Value = fieldRow.Group
        childNode.Attributes.RemoveNamedItem("Version")
        childNode.Attributes.RemoveNamedItem("StaticName")
        If Not methodNumber = updateMethodNumber Then
            childNode.Attributes.RemoveNamedItem("ID")
            childNode.Attributes.RemoveNamedItem("SourceID")
        End If
        Dim newMethod As Xml.XmlNode = fields.AppendChild(fields.OwnerDocument.CreateElement("Method", fields.NamespaceURI))
        newMethod.Attributes.RemoveAll()
        newMethod.Attributes.Append(fields.OwnerDocument.CreateAttribute("ID")).Value = methodNumber
        newMethod.AppendChild(childNode)
    End Sub

    Private ReadOnly Property IsSameSiteCollection() As Boolean
        Get
            Dim srcSC As Xml.XmlNode = Me.SourceWeb.GetAllSubWebCollection
            Dim dstSC As Xml.XmlNode = Me.DestinationWeb.GetAllSubWebCollection

            If srcSC.OuterXml = dstSC.OuterXml Then
                Return True
            Else
                Return False
            End If
        End Get
    End Property

#Region "SourceWeb and DestinationWeb"
    Enum WebRefs
        Source
        Destination
    End Enum

    Private _webRef As WebRefs = Nothing

    Private Property WebRef() As WebRefs
        Get
            Return _webRef
        End Get
        Set(ByVal value As WebRefs)
            Dim UrlPart As String = Nothing
            Select Case value
                Case WebRefs.Destination
                    UrlPart = Me.TextBoxDestination.Text
                Case WebRefs.Source
                    UrlPart = Me.TextBoxSource.Text
            End Select
            My.WebServices.Webs.Url = UrlPart.TrimEnd("\/".ToCharArray) & "/_vti_bin/webs.asmx"
            _webRef = value
        End Set
    End Property

    Private ReadOnly Property SourceWeb() As Webs
        Get
            WebRef = WebRefs.Source
            Return My.WebServices.Webs
        End Get
    End Property

    Private ReadOnly Property DestinationWeb() As Webs
        Get
            WebRef = WebRefs.Destination
            Return My.WebServices.Webs
        End Get
    End Property
#End Region

#Region "Copy Update Check / Button Change"

    Private ReadOnly Property IsUpdate() As Boolean
        Get
            Return Me.TextBoxSource.Text = Me.TextBoxDestination.Text
        End Get
    End Property
#End Region

    Private Sub TextBoxSource_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBoxSource.TextChanged
        Me.ButtonCopy.Visible = False
    End Sub

End Class
